package com.xuecheng.manage_cms_client.service;

import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSDownloadStream;
import com.mongodb.client.gridfs.model.GridFSFile;
import com.xuecheng.framework.domain.cms.CmsPage;
import com.xuecheng.framework.domain.cms.CmsSite;
import com.xuecheng.framework.domain.cms.response.CmsCode;
import com.xuecheng.framework.exception.ExceptionCast;
import com.xuecheng.manage_cms_client.dao.CmsPageRepository;
import com.xuecheng.manage_cms_client.dao.CmsSiteRepository;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsResource;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.stereotype.Service;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Optional;

@Service
public class PageService {
    private static final Logger LOGGER = LoggerFactory.getLogger(PageService.class);

    @Autowired
    private CmsPageRepository cmsPageRepository;

    @Autowired
    private CmsSiteRepository cmsSiteRepository;

    @Autowired
    private GridFsTemplate gridFsTemplate;

    @Autowired
    private GridFSBucket gridFSBucket;

    public void savePageToServerPath(String pageId){
        //获取页面
        Optional<CmsPage> cmsPageOptional = cmsPageRepository.findById(pageId);
        if(!cmsPageOptional.isPresent()){
            ExceptionCast.cast(CmsCode.CMS_PAGE_NOTEXISITS);
        }
        CmsPage cmsPage = cmsPageOptional.get();


        //获取站点
        String siteId = cmsPage.getSiteId();
        Optional<CmsSite> cmsSiteOptional = cmsSiteRepository.findById(siteId);
        if(!cmsSiteOptional.isPresent()){
            ExceptionCast.cast(CmsCode.CMS_SITE_NOTEXISTS);
        }
        CmsSite cmsSite =  cmsSiteOptional.get();

        //将静态页面保存到服务器指定路径
        String htmlFileId = cmsPage.getHtmlFileId();
        String pagePath = cmsSite.getSitePhysicalPath() + cmsPage.getPagePhysicalPath() + cmsPage.getPageName();

        this.savePageByFileId(htmlFileId, pagePath);
    }

    /**
     * 根据文件标识从gridfs中获取文件输入流
     * @param fileId
     * @return
     */
    public InputStream getFileById(String fileId){
        //主键查询
        InputStream inputStream = null;
        try {
            GridFSFile gridFSFile = gridFsTemplate.findOne(Query.query(Criteria.where("_id").is(fileId)));
            GridFSDownloadStream gridFSDownloadStream = gridFSBucket.openDownloadStream(gridFSFile.getObjectId());
            GridFsResource gridFsResource = new GridFsResource(gridFSFile, gridFSDownloadStream);
            inputStream = gridFsResource.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
        return inputStream;
    }

    /**
     * 根据gridfs文件标识将gridfs文件保存到服务器指定物理路径。
     * @param htmlFileId
     * @param pagePath
     */
    private void savePageByFileId(String htmlFileId, String pagePath){
        //htmlFileId获取html页面输入流
        InputStream inputStream = this.getFileById(htmlFileId);
        if(inputStream == null){
            ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_HTMLISNULL);
        }

        //pagePath获取文件输出流
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(pagePath);
            //流对接
            IOUtils.copy(inputStream, fileOutputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            LOGGER.error("创建文件失败" + pagePath);
        } catch (IOException e) {
            e.printStackTrace();
            LOGGER.error("流复制失败" + pagePath);
        } finally {
            if (fileOutputStream != null){
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
